package myjwt

import (
	"encoding/json"
	"errors"
	"time"

	"github.com/dgrijalva/jwt-go"
)

// JwtConf ..
type JwtConf struct {
	Issuer   string // 发行商
	Subject  string // 主题
	Audience string // 观众
	Secret   string // 密钥
	Days     int    // 有效期天数
}

//type UserNameClaims struct {
//	Username string `json:"username"`
//	Password string `json:"password"`
//	jwt.StandardClaims
//}
//
//const (
//	secret = "sssasee"
//	issuer = "test"
//)
//var jwtSecret = []byte(secret)
//
//func GenerateTokenByUserName(username, password string) (string, error) {
//	nowTime := time.Now()
//	expireTime := nowTime.AddDate(0, 1, 1)
//	claims := UserNameClaims{
//		username,
//		password,
//		jwt.StandardClaims{
//			ExpiresAt: expireTime.Unix(),
//			Issuer:    issuer,
//		},
//	}
//	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
//	return tokenClaims.SignedString(jwtSecret)
//}
//func ParseTokenByUserName(token string) (*UserNameClaims, error) {
//	tokenClaims, err := jwt.ParseWithClaims(token, &UserNameClaims{}, func(token *jwt.Token) (interface{}, error) {
//		return jwtSecret, nil
//	})
//	if err == nil && tokenClaims != nil {
//		if claims, ok := tokenClaims.Claims.(*UserNameClaims); ok && claims.Valid() == nil {
//			return claims, nil
//		}
//	}
//	return nil, err
//}

// GenerateToken 生成token
func GenerateToken(id string, conf JwtConf) (string, error) {
	nowTime := time.Now()
	expireTime := nowTime.AddDate(0, 0, conf.Days)
	claims := jwt.StandardClaims{
		Audience:  conf.Audience,
		ExpiresAt: expireTime.Unix(),
		Id:        id, // strconv.Itoa(int(id))
		IssuedAt:  nowTime.Unix(),
		Issuer:    conf.Issuer,
		NotBefore: nowTime.Unix(),
		Subject:   conf.Subject,
	}
	tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return tokenClaims.SignedString([]byte(conf.Secret))
}

// ParseToken 解析token
func ParseToken(token string, conf JwtConf) (jwt.StandardClaims, error) {
	var (
		t         *jwt.Token
		err       error
		jwtClaims jwt.StandardClaims
		jwtSecret = []byte(conf.Secret)
	)
	if token != "" {
		t, err = jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
			return jwtSecret, nil
		})
		if err == nil {
			if claims, ok := t.Claims.(jwt.MapClaims); ok && claims.Valid() == nil {
				str, e := json.Marshal(claims)
				if e == nil {
					if err = json.Unmarshal(str, &jwtClaims); err == nil {
						if conf.Issuer != jwtClaims.Issuer { //  || conf.Subject != jwtClaims.Subject
							err = errors.New("token is invalid")
						} else {
							nowTime := time.Now()
							if jwtClaims.NotBefore > 0 {
								if nbefore := time.Unix(jwtClaims.NotBefore, 0); nbefore.After(nowTime) {
									err = errors.New("token is not active")
								}
							}
							if err == nil && jwtClaims.ExpiresAt > 0 {
								if expires := time.Unix(jwtClaims.ExpiresAt, 0); expires.Before(nowTime) {
									err = errors.New("token expired")
								}
							}
						}
					}
				} else {
					err = e
				}
			} else if claims != nil {
				err = claims.Valid()
			} else {
				err = errors.New("token valid fail")
			}
		}
	} else {
		err = errors.New("token is empty")
	}
	return jwtClaims, err
}
